package com.isyscore.os.core.util;

import com.isyscore.device.common.util.Splitters;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * 从请求中获取对应值
 *
 * @author felixu
 * @since 2021.11.16
 */
public class RequestUtils {

    /**
     * 获取 Request
     *
     * @return 可能为空
     */
    public static Optional<HttpServletRequest> getHttpServletRequest() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        if (null != attributes)
            return Optional.of(((ServletRequestAttributes) attributes).getRequest());
        return Optional.empty();
    }

    /**
     * 获取请求头内容
     *
     * @return 可能为空
     */
    public static Map<String, String> getHeaders(HttpServletRequest request) {
        Objects.requireNonNull(request, "http servlet request must be not null");
        Map<String, String> map = new LinkedHashMap<>();
        Enumeration<String> enumeration = request.getHeaderNames();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }

    /**
     * 获取请求头内容
     *
     * @return 可能为空
     */
    public static Optional<Map<String, String>> getHeaders() {
        return getHttpServletRequest().map(RequestUtils::getHeaders);
    }

    /**
     * 获取请求参数
     *
     * @return 可能为空
     */
    public static Map<String, String> getParams(HttpServletRequest request) {
        Objects.requireNonNull(request, "http servlet request must be not null");
        Map<String, String> param = new LinkedHashMap<>();
        request.getParameterMap().forEach((k, v) -> param.put(k, String.join(",", v)));
        return param;
    }

    /**
     * 获取请求参数
     *
     * @return 可能为空
     */
    public static Optional<Map<String, String>> getParams() {
        return getHttpServletRequest().map(RequestUtils::getParams);
    }

    /**
     * 获取请求者 IP
     *
     * @return 可能为空
     */
    public static String getIpAddress(HttpServletRequest request) {
        Objects.requireNonNull(request, "http servlet request must be not null");
        // 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } else if (ip.length() > 15) {
            List<String> ips = Splitters.COMMA.splitToList(ip);
            for (String val : ips) {
                if (!("unknown".equalsIgnoreCase(val))) {
                    ip = val;
                    break;
                }
            }
        }
        return ip;
    }

    /**
     * 获取请求者 IP
     *
     * @return 可能为空
     */
    public static Optional<String> getIpAddress() {
        return getHttpServletRequest().map(RequestUtils::getIpAddress);
    }

    /**
     * 获取 web 的绝对路径
     *
     * @return 可能为空
     */
    public static String getBasePath(HttpServletRequest request) {
        Objects.requireNonNull(request, "http servlet request must be not null");
        return request.getScheme() + "://" + request.getServerName() + ":" +
                request.getServerPort() + request.getContextPath() + "/";
    }

    /**
     * 获取 web 的绝对路径
     *
     * @return 可能为空
     */
    public static Optional<String> getBasePath() {
        return getHttpServletRequest().map(RequestUtils::getBasePath);
    }
}
